package etcd

import (
	"context"
	"errors"
	"lnzw/engine/log"
	"sync"
	"time"

	"go.etcd.io/etcd/clientv3"
	"go.uber.org/zap"
)

var onece = sync.Once{}
var GlobalEtcd *clientv3.Client

var (
	ErrEMPTY = errors.New("key is empty")
)

func Setup() error {
	var errrs error
	onece.Do(func() {
		endpoints := []string{"192.168.31.70:22379"}
		client, err := clientv3.New(clientv3.Config{
			Endpoints:   endpoints,
			DialTimeout: 5 * time.Second,
		})
		if err != nil {
			errrs = err
			log.Logger.Error("etcd connect failed", zap.Error(err))
			return
		}
		ctx, cancle := context.WithTimeout(context.Background(), 5*time.Second)
		_, err = client.Status(ctx, endpoints[0])
		defer cancle()
		if err != nil {
			errrs = err
			log.Logger.Error("etcd connect failed", zap.Error(err))
			return
		}
		log.Logger.Info("etcd connect success")
		GlobalEtcd = client
	})
	return errrs
}

func Put(key string, value string) (bool, error) {
	_, err := GlobalEtcd.Put(context.Background(), key, value)
	return err == nil, err
}

func Get(key string) (string, error) {
	rsp, err := GlobalEtcd.Get(context.Background(), key)
	if err != nil {
		return "", err
	}
	if len(rsp.Kvs) == 0 { // key不存在
		return "", ErrEMPTY
	}
	return string(rsp.Kvs[0].Value), nil
}

func GetAll(prefix string) (map[string]string, error) {
	rsp, err := GlobalEtcd.Get(context.Background(), prefix, clientv3.WithPrefix())
	if err != nil {
		return nil, err
	}
	data := make(map[string]string)
	for _, kv := range rsp.Kvs {
		data[string(kv.Key)] = string(kv.Value)
	}
	return data, nil
}

func Delete(key string) (bool, error) {
	_, err := GlobalEtcd.Delete(context.Background(), key)
	return err == nil, err
}

func Close() {
	if GlobalEtcd != nil {
		GlobalEtcd.Close()
		GlobalEtcd = nil
	}
}
